#include <physics/UnknownJoint.h>
#include <Box2D/Dynamics/Joints/b2Joint.h>

#include <physics/DistanceJoint.h>
#include <physics/RevoluteJoint.h>
#include <physics/MouseJoint.h>

namespace liba
{
namespace converter
{
	converter::EnumPair<char, b2JointType> JointTypeNames[] = 
	{
		converter::MakeEnumPair("Revolute", e_revoluteJoint),
		converter::MakeEnumPair("Prismatic", e_prismaticJoint),
		converter::MakeEnumPair("Distance", e_distanceJoint),
		converter::MakeEnumPair("Pulley", e_pulleyJoint),
		converter::MakeEnumPair("Mouse", e_mouseJoint),
		converter::MakeEnumPair("Gear", e_gearJoint),
		converter::MakeEnumPair("Wheel", e_wheelJoint),
		converter::MakeEnumPair("Weld", e_weldJoint),
		converter::MakeEnumPair("Friction", e_frictionJoint),
		converter::MakeEnumPair("Rope", e_ropeJoint),
	};

	template<> struct ConverterTraits<char, b2JointType>
		:	public ConverterTraitsEnumBase<char, b2JointType, JointTypeNames>
	{};

} // namespace converter
} // namespace liba



namespace physics
{

UnknownJoint::UnknownJoint(World *world)
	: Joint(world),
	typedJoint(NULL)
{
}

UnknownJoint::~UnknownJoint()
{
}

bool UnknownJoint::on_attribute(xml::Provider * prov, const std::string & name, const std::string & value)
{
	if(name == "Type")
	{
		b2JointType type;
		if(!converter::convert(value, &type))
			return false;

		switch(type)
		{
		case e_distanceJoint:	typedJoint = new DistanceJoint(world); break;
		case e_revoluteJoint:	typedJoint = new RevoluteJoint(world); break;
		case e_mouseJoint:		typedJoint = new MouseJoint(world);    break;
/*
		case e_prismaticJoint:	typedJoint = new PrismaticJoint(world); break;
		case e_pulleyJoint:		typedJoint = new PulleyJoint(world); break;
		case e_gearJoint:		typedJoint = new GearJoint(world); break;
		case e_wheelJoint:		typedJoint = new WheelJoint(world); break;
		case e_weldJoint:		typedJoint = new WeldJoint(world); break;
		case e_frictionJoint:	typedJoint = new FrictionJoint(world); break;
		case e_ropeJoint:		typedJoint = new RopeJoint(world); break;
*/
		default:
			return false;
		}

		typedJoint->CopyFrom(this);
		
		return true;
	}

	if(typedJoint)
		return typedJoint->on_attribute(prov, name, value);

	return Joint::on_attribute(prov, name, value);
}

bool UnknownJoint::on_node(xml::Provider *prov, const std::string &name)
{
	if(typedJoint)
		return typedJoint->on_node(prov, name);

	return Joint::on_node(prov, name);
}

}